import { createDirectory, safeRemove } from '@platformatic/foundation'
import { deepStrictEqual, ok } from 'node:assert'
import { readFile, symlink, writeFile } from 'node:fs/promises'
import { basename, resolve } from 'node:path'
import { test } from 'node:test'
import { request } from 'undici'
import { prepareRuntime } from '../../basic/test/helper.js'
import { version } from '../lib/version.js'
import { changeWorkingDirectory, createTemporaryDirectory, waitForStart, wattpm, wattpmUtils } from './helper.js'

const schema = `https://schemas.platformatic.dev/@platformatic/node/${version}.json?autogenerated=true`

for (const command of ['install', 'update', 'import', 'resolve', 'patch-config']) {
  test(`${command} - when no configuration file exists, should create a watt.json automatically and fail due to missing dependency`, async t => {
    const rootDir = await createTemporaryDirectory(t, 'cli-build')
    await writeFile(resolve(rootDir, 'index.js'), '{}', 'utf-8')

    changeWorkingDirectory(t, rootDir)
    const wattProcess = await wattpmUtils(command, rootDir, { reject: false })

    deepStrictEqual(wattProcess.exitCode, 1)
    ok(
      wattProcess.stdout.includes(
        'We have auto-detected that the current folder is a generic Node.js application so we have created a watt.json file for you automatically.'
      )
    )
    ok(
      wattProcess.stdout.includes(
        'Cannot load module @platformatic/node. Please add it to your package.json and try again.'
      )
    )

    deepStrictEqual(
      await readFile(resolve(rootDir, 'watt.json'), 'utf-8'),
      JSON.stringify({ $schema: schema }, null, 2)
    )
  })
}

test('import - when no configuration file exists, should create a watt.json automatically and install required dependencies', async t => {
  const rootDir = await createTemporaryDirectory(t, 'cli-build')
  await writeFile(
    resolve(rootDir, 'index.js'),
    `
import { createServer } from 'node:http'

const server = createServer((req, res) => {
  res.writeHead(200, { 'content-type': 'application/json', connection: 'close' }).end(JSON.stringify({ ok: true }))
})

server.listen(3000)
  `,
    'utf-8'
  )

  changeWorkingDirectory(t, rootDir)
  const wattProcess = await wattpmUtils('import', '-P', 'pnpm')

  ok(
    wattProcess.stdout.includes(
      'We have auto-detected that the current folder is a generic Node.js application so we have created a watt.json file for you automatically.'
    )
  )

  ok(
    wattProcess.stdout.includes(
      `Application ${basename(rootDir)} is a generic Node.js application. Adding @platformatic/node to its package.json dependencies.`
    )
  )

  // Replace some dependences with symlinks to local packages
  const modulesDir = resolve(rootDir, 'node_modules/@platformatic')
  await safeRemove(resolve(modulesDir, 'basic'))
  await safeRemove(resolve(modulesDir, 'node'))
  await symlink(resolve(import.meta.dirname, '../../basic'), resolve(modulesDir, 'basic'), 'dir')
  await symlink(resolve(import.meta.dirname, '../../node'), resolve(modulesDir, 'node'), 'dir')

  // Check that the application can start
  const startProcess = wattpm('dev', rootDir)

  const { url } = await waitForStart(startProcess)

  const { statusCode, body } = await request(url)
  deepStrictEqual(statusCode, 200)
  deepStrictEqual(await body.json(), { ok: true })

  startProcess.kill('SIGINT')
  await startProcess.catch(() => {})
})

test('import - it should fail with a folder with no recognized files', async t => {
  const { root: rootDir } = await prepareRuntime(t, 'main', false, 'watt.json')
  t.after(() => safeRemove(rootDir))

  const emptyDir = resolve(rootDir, 'web/empty')
  await createDirectory(emptyDir)
  changeWorkingDirectory(t, rootDir)
  const wattProcess = await wattpmUtils('import', '-P', 'pnpm', { reject: false })

  deepStrictEqual(wattProcess.exitCode, 1)
  ok(wattProcess.stdout.includes(`The path ${emptyDir} does not contain a supported application.`))
})
